package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

const (
	FIRING   = "警告"
	RESOLVED = "恢复"
)

// alert  告警信息结构体
type Alert struct {
	// 告警名称
	alertname string
	// 告警状态
	status string
	// 实例ip
	instance string
	// 开始时间
	startsAt time.Time
	// 结束时间
	endsAt time.Time
	// 告警简况
	summary string
	// 告警详情
	description string
}

// 企业微信token处理，2小时过期问题
type Token struct {
	// token 串
	AccessToken string `json:"access_token"`
	// 过期时长
	ExpiresIn int64 `json:"expires_in"`
	// token 生成时间
	createTime time.Time
}

// 请求参数筛选提取
func processRequest(param []byte) (s []Alert, err error) {
	var a Alert
	var paramJson interface{}
	// 请求参数json转换
	err = json.Unmarshal(param, &paramJson)
	if err != nil {
		fmt.Println(err)
		return
	}
	// 整个请求报文转换为map断言
	reqMap, ok := paramJson.(map[string]interface{})
	if !ok {
		err = fmt.Errorf("%s", "reqMap转换map失败")
		return
	}
	// 获取alerts，断言为切片接口 []interface{}
	sliceAlerts, ok := reqMap["alerts"].([]interface{})
	if !ok {
		err = fmt.Errorf("%s", "sliceAlerts转换切片失败")
		return
	}
	// 获取sliceAlerts第0号元素，断言map类型
	for _, sAlert := range sliceAlerts {
		mapAlerts, ok := sAlert.(map[string]interface{})
		if !ok {
			err = fmt.Errorf("%s", "mapAlerts转换map失败")
			return
		}

		// 获取Alerts.Labels，断言map类型
		mapAlertsLables, ok := mapAlerts["labels"].(map[string]interface{})
		if !ok {
			err = fmt.Errorf("%s", "mapAlerts labels 转map失败")
			return
		}
		// alerts.annotations 转map 断言
		mapAlertsAnnotations, ok := mapAlerts["annotations"].(map[string]interface{})
		if !ok {
			err = fmt.Errorf("%s", "mapAlerts annotations 转map失败")
			return
		}

		a.status = fmt.Sprint(mapAlerts["status"])
		a.instance = fmt.Sprint(mapAlertsLables["instance"])
		a.alertname = fmt.Sprint(mapAlertsLables["alertname"])
		start, e := time.Parse("2006-01-02T15:04:05.999999999Z07", fmt.Sprint(mapAlerts["startsAt"]))
		if e != nil {
			e = fmt.Errorf("startsAt 时间字符串转换失败：%s", err)
			return nil, e
		}
		startAt, e := processTime(start)
		if e != nil {
			e = fmt.Errorf("startsAt 时间处理失败：%s", err)
			return nil, e
		}
		a.startsAt = startAt
		ends, e := time.Parse("2006-01-02T15:04:05.999999999Z07", fmt.Sprint(mapAlerts["endsAt"]))
		if e != nil {
			e = fmt.Errorf("endsAt 时间字符串转换失败：%s", err)
			return nil, e
		}
		endsAt, e := processTime(ends)
		if e != nil {
			e = fmt.Errorf("endsAt 时间处理失败：%s", err)
			return nil, e
		}
		a.endsAt = endsAt
		a.summary = fmt.Sprint(mapAlertsAnnotations["summary"])
		a.description = fmt.Sprint(mapAlertsAnnotations["description"])
		s = append(s, a)
	}
	return s, nil
}

//处理prometheus时间+8小时
func processTime(in time.Time) (out time.Time, err error) {
	h, err := time.ParseDuration("8h")
	if err != nil {
		return
	}
	out = in.Add(h)
	return
}

// 邮件 结构体转换成告警格式
func processAlertToString(s []Alert) string {
	// 告警状态
	// 实例ip
	// 开始时间
	// 结束时间
	// 告警简况
	// 告警详情
	var rStr string
	for _, a := range s {
		var f1Str string
		if a.status == "resolved" {
			f1Str = fmt.Sprintf(`<p style="font-size: 30; color: green;font-weight: bold;">%s</p> `, RESOLVED)
		} else {
			f1Str = fmt.Sprintf(`<p style="font-size: 30; color: red;font-weight: bold;">%s</p> `, FIRING)
		}

		f2Str := fmt.Sprintf(`
		<p>实例ip:   %s</p>
		<p>开始时间: %s</p>
		<p>结束时间: %s</p>
		<p>告警简况: %s</p>
		<p>告警详情: %s</p>
	`, a.instance, a.startsAt, a.endsAt, a.summary, a.description)
		rStr = rStr + f1Str + f2Str
	}
	return rStr
}

// 获取token ，如当前token在有效时间内直接返回，否则获取新token
func getAccessToken() (t Token, err error) {
	t.createTime = time.Now()
	corpid := configMap["qywechat"]["corpid"]
	corpsecret := configMap["qywechat"]["corpsecret"]
	requestUrl := configMap["qywechat"]["tokenurl"]
	paraData := url.Values{}
	paraData.Set("corpid", corpid)
	paraData.Set("corpsecret", corpsecret)
	u, err := url.ParseRequestURI(requestUrl)
	if err != nil {
		fmt.Printf("ParseRequestURI, err:%v\n", err)
		return
	}
	u.RawQuery = paraData.Encode()
	resp, err := http.Get(u.String())
	if err != nil {
		fmt.Printf("Get failed, err:%v\n", err)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("get resp failed, err:%v\n", err)
		return
	}
	// fmt.Println(string(b))
	err = json.Unmarshal(b, &t)
	if err != nil {
		fmt.Printf("获取token时json转结构体出错%v", err)
		return
	}
	return
}

// 处理告警信息转换成企业微信需要json请求体
func processAlertToJsonStr(s []Alert) (str string) {
	for _, a := range s {
		if a.status == "resolved" {
			str = str + fmt.Sprintf(`***  %s  ***\n\n`, RESOLVED)
		} else {
			str = str + fmt.Sprintf(`***  %s  ***\n\n`, FIRING)
		}
		str += fmt.Sprintf(`实例IP： %s\n`, a.instance)
		str += fmt.Sprintf(`开始时间： %s\n`, a.startsAt)
		str += fmt.Sprintf(`结束时间： %s\n`, a.endsAt)
		str += fmt.Sprintf(`告警简况： %s\n`, a.summary)
		str += fmt.Sprintf(`告警详情： %s\n\n`, a.description)
	}
	return
}
